﻿using DXBase.D3D;
using DXBase.Structs;
using Windows.UI;

namespace DXBase.Scenes
{
	public abstract class D3DScene : IScene
	{
		public D3DScene()
		{
			StartCamera = new Camera()
			{
				EyeLocation = new Vector3F(0, 0.0f, 0.0f),
				LookVector = new Vector3F(0, 0, 100),
				UpVector = new Vector3F(0, 1, 0),
				FarPlane = 800,
			};
			CameraController = new CameraController { Camera = StartCamera.Clone() };
			Background = Colors.Black;

			PerObjectData = new ConstantBuffer<PerObjectData>(new PointerPerObjectData()) { Count = 1 };
			PerFrameData = new ConstantBuffer<PerFrameData>(new PointerPerFrameData()) { Count = 1 };
			DirLights = new ConstantBuffer<DirectionalLight>(new PointerDirectionalLight());
			PointLights = new ConstantBuffer<PointLight>(new PointerPointLight());
			SpotLights = new ConstantBuffer<SpotLight>(new PointerSpotLight());
			Sampler = new SamplerState();
		}
		public SamplerState Sampler { get; private set; }
		public ConstantBuffer<PerObjectData> PerObjectData { get; private set; }
		public ConstantBuffer<PerFrameData> PerFrameData { get; private set; }
		public PerObjectData PerObject 
		{
			get { return PerObjectData[0]; }
			set { PerObjectData[0] = value; }
		}
		public PerFrameData PerFrame
		{
			get { return PerFrameData[0]; }
			set { PerFrameData[0] = value; }
		}
		public ConstantBuffer<DirectionalLight> DirLights { get; private set; }
		public ConstantBuffer<PointLight> PointLights { get; protected set; }
		public ConstantBuffer<SpotLight> SpotLights { get; protected set; }
		public int NumUsedDirectionLights, NumUsedPointLights, NumUsedSpotLights;

		public virtual void Render(DXContext ctxt)
		{
			var g = new D3DGraphic(ctxt);
			Render(g);
		}
		public virtual void Render(D3DGraphic ctxt) { }
		public virtual void Update(DXContext ctxt, PerformanceTimer ptimer) 
		{
			if (CameraController != null)
				CameraController.Update(ptimer);

			var cam = CameraController != null ? CameraController.Camera : Camera;
			DirLights.Count = 3;
			PointLights.Count = 20;
			SpotLights.Count = 20;
			PerFrame = new PerFrameData
			{
				gEyePosW = cam.EyeLocation,
				nDirLights = NumUsedDirectionLights,
				nPointLights = NumUsedPointLights,
				nSpotLight = NumUsedSpotLights,
			};
		}

		#region StartCamera, CameraController, Camera, Inputcontroller

		public Camera StartCamera 
		{
			get { return mStartCamera; }
			set
			{
				if (value == mStartCamera) return;
				mStartCamera = value;
				if (value != null && CameraController != null)
					CameraController.Camera = value.Clone();
			}
		}
		Camera mStartCamera;
		public CameraController CameraController { get; protected set; }
		public Camera Camera { get { return CameraController != null ? CameraController.Camera : StartCamera; } }

		public InputController Inputcontroller
		{
			get { return iController; }
			set
			{
				if (value == iController)
					return;
				iController = value;
				OnInputControllerChanged();
			}
		}
		InputController iController;

		protected virtual void OnInputControllerChanged()
		{
			if (CameraController != null)
				CameraController.InputController = Inputcontroller;
		}

		#endregion

		public Color4F Background { get; set; }
	}
}
